﻿/*
Adapted from AAPlus library by PJ Naughter
Permission was granted to convert the library to C#

This source is modified from PJ Naugters AA+ lib
(http://www.naughter.com/aa.html)
and therefore is covered under his copyright license, which
is as follows:

Purpose: Implementation for the algorithms which obtain the position of the Sun
Created: PJN / 29-12-2003
History: PJN / 17-01-2007 1. Changed name of CAASun::ApparentEclipticLongtitude to 
                          CAASun::ApparentEclipticLongitude. Thanks to Mathieu Peyréga for reporting this
                          typo!.
         PJN / 26-07-2008 1. Changed name of CAASun::EclipticRectangularCoordinatesMeanEquinox to
                          CAASun::EquatorialRectangularCoordinatesMeanEquinox to refer to the fact that it 
                          returns equatorial coordinates instead of ecliptic coordinates. Thanks to Frank 
                          Trautmann for reporting this issue
                          2. Updated copyright details.
                          3. zip file now ships with a VC 2005 solution instead of a VC 6 solution file.
                          4. Code now compiles cleanly using Code Analysis (/analyze)

Copyright (c) 2003 - 2009 by PJ Naughter (Web: www.naughter.com, Email: pjna@naughter.com)

All rights reserved.

Copyright / Usage Details:

You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise) 
when your product is released in binary form. You are allowed to modify the source code in any way you want 
except you cannot modify the copyright details at the top of each module. If you want to distribute source 
code with your application, then you are only allowed to distribute versions released by the author. This is 
to maintain a single distribution point for the source code. 

*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AAPlus
{
    public static class Sun
    {

        public static double GeometricEclipticLongitude(double JD)
        {
            return CoordinateTransformation.MapTo0To360Range(Earth.EclipticLongitude(JD) + 180);
        }

        public static double GeometricEclipticLatitude(double JD)
        {
            return -Earth.EclipticLatitude(JD);
        }

        public static double GeometricEclipticLongitudeJ2000(double JD)
        {
            return CoordinateTransformation.MapTo0To360Range(Earth.EclipticLongitudeJ2000(JD) + 180);
        }

        public static double GeometricEclipticLatitudeJ2000(double JD)
        {
            return -Earth.EclipticLatitudeJ2000(JD);
        }

        public static double GeometricFK5EclipticLongitude(double JD)
        {
            //Convert to the FK5 stystem
            double Longitude = GeometricEclipticLongitude(JD);
            double Latitude = GeometricEclipticLatitude(JD);
            Longitude += FK5.CorrectionInLongitude(Longitude, Latitude, JD);

            return Longitude;
        }

        public static double GeometricFK5EclipticLatitude(double JD)
        {
            //Convert to the FK5 stystem
            double Longitude = GeometricEclipticLongitude(JD);
            double Latitude = GeometricEclipticLatitude(JD);
            double SunLatCorrection = FK5.CorrectionInLatitude(Longitude, JD);
            Latitude += SunLatCorrection;

            return Latitude;
        }

        public static double ApparentEclipticLongitude(double JD)
        {
            double Longitude = GeometricFK5EclipticLongitude(JD);

            //Apply the correction in longitude due to nutation
            Longitude += CoordinateTransformation.DMSToDegrees(0, 0, Nutation.NutationInLongitude(JD));

            //Apply the correction in longitude due to aberration
            double R = Earth.RadiusVector(JD);
            Longitude -= CoordinateTransformation.DMSToDegrees(0, 0, 20.4898 / R);

            return Longitude;
        }

        public static double ApparentEclipticLatitude(double JD)
        {
            return GeometricFK5EclipticLatitude(JD);
        }

        public static Coordinate3D EquatorialRectangularCoordinatesMeanEquinox(double JD)
        {
            double Longitude = CoordinateTransformation.DegreesToRadians(GeometricFK5EclipticLongitude(JD));
            double Latitude = CoordinateTransformation.DegreesToRadians(GeometricFK5EclipticLatitude(JD));
            double R = Earth.RadiusVector(JD);
            double epsilon = CoordinateTransformation.DegreesToRadians(Nutation.MeanObliquityOfEcliptic(JD));

            Coordinate3D value = new Coordinate3D();
            value.X = R * Math.Cos(Latitude) * Math.Cos(Longitude);
            value.Y = R * (Math.Cos(Latitude) * Math.Sin(Longitude) * Math.Cos(epsilon) - Math.Sin(Latitude) * Math.Sin(epsilon));
            value.Z = R * (Math.Cos(Latitude) * Math.Sin(Longitude) * Math.Sin(epsilon) + Math.Sin(Latitude) * Math.Cos(epsilon));

            return value;
        }

        public static Coordinate3D EclipticRectangularCoordinatesJ2000(double JD)
        {
            double Longitude = GeometricEclipticLongitudeJ2000(JD);
            Longitude = CoordinateTransformation.DegreesToRadians(Longitude);
            double Latitude = GeometricEclipticLatitudeJ2000(JD);
            Latitude = CoordinateTransformation.DegreesToRadians(Latitude);
            double R = Earth.RadiusVector(JD);

            Coordinate3D value = new Coordinate3D();
            double coslatitude = Math.Cos(Latitude);
            value.X = R * coslatitude * Math.Cos(Longitude);
            value.Y = R * coslatitude * Math.Sin(Longitude);
            value.Z = R * Math.Sin(Latitude);

            return value;
        }


        public static Coordinate3D EquatorialRectangularCoordinatesJ2000(double JD)
        {
            Coordinate3D value = EclipticRectangularCoordinatesJ2000(JD);
            value = FK5.ConvertVSOPToFK5J2000(value);

            return value;
        }

        public static Coordinate3D EquatorialRectangularCoordinatesB1950(double JD)
        {
            Coordinate3D value = EclipticRectangularCoordinatesJ2000(JD);
            value = FK5.ConvertVSOPToFK5B1950(value);

            return value;
        }

        public static Coordinate3D EquatorialRectangularCoordinatesAnyEquinox(double JD, double JDEquinox)
        {
            Coordinate3D value = EquatorialRectangularCoordinatesJ2000(JD);
            value = FK5.ConvertVSOPToFK5AnyEquinox(value, JDEquinox);

            return value;
        }

    }
}
